package com.zm.cinema.controller;

import com.zm.cinema.entity.Result;
import com.zm.cinema.entity.User;
import com.zm.cinema.util.QRCodeUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;

import javax.servlet.http.HttpSession;
import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/*
在后台将访问手机登录页面的地址生成二维码
生成扫描登录二维码，同时生成token,然后将token放入ScanLoginInfo对象，将ScanLoginInfo对象存入redis中设置有效时间
将两二维码渲染到前端页面，渲染成功后,会发送一个请求获取token,pc前端会与后端建立websocke连接，根据token将wensocket连接的session对象存入一个静态的hashmap中
使用手机扫描第一个二维码进入手机登录页面，输入账号密码登录，会将用户信息存入手机，之后每次访问都会自动登录
手机登录成功后，再使用手机扫描扫码登录二维码，手机扫码后会发送一个携带token请求到后端
后端接收请求后，根据token取出之前存入的redis中ScanLoginInfo对象判断二维码是否失效，失效提示用户登录二维码失效重新生成，未失效会从手机连接的Httpsession对象中取出用户数据，将用户数据放入ScanLoginInfo继续存入redis后，通知使用websocket的session对象pc前端用户扫码成功
pc前端收到websocket的通知后，会向后端发送一个请求获取用户信息，
后端收到请求后，会根据token从redis取出用户数据，存入pc连接的Httpsession对象中，然后将用户数据发送到pc前端
pc前端获取到用户数据，完成扫码自动登录


 */

@RestController
@RequestMapping("qrcode")
@ServerEndpoint("/autoLogin/{token}")
public class QrCodeDo {

    public static final String MY_HEAD = "F:/yuancheng/javaproject/s3/课程资料/SpringBoot/案例/a.jpg";
    @RequestMapping(path = "image",produces = MediaType.IMAGE_JPEG_VALUE)
    public void image(String content, OutputStream out) throws Exception {
        QRCodeUtil.encode(content,MY_HEAD,out,true);
    }

    @RequestMapping(path = "mobile",produces = MediaType.IMAGE_JPEG_VALUE)
    public void toMobile(OutputStream out) throws Exception {
       image("http://192.168.4.108:8080/mobile/index.html",out);
    }

    @Autowired
    RedisTemplate redisTemplate;

    @RequestMapping(path = "createLoginQrcode",produces = MediaType.IMAGE_JPEG_VALUE)
    public void createLoginQrcode(HttpSession session,OutputStream out) throws Exception {
        //生成令牌 UUID
        String uuid= UUID.randomUUID().toString();
        ScanLoginInfo sli = new ScanLoginInfo(uuid,"未扫码",null);
        ValueOperations opsForValue = redisTemplate.opsForValue();
        opsForValue.set("scanLogin:"+uuid,sli,60, TimeUnit.SECONDS);
        String content = "http://192.168.4.108:8080/qrcode/scanLoginQrcode?token="+uuid;
        session.setAttribute("loginToken",uuid);
        image(content,out);
    }

    @Value("${sgin.session-key}")
    String sessionKey;

    @RequestMapping("scanLoginQrcode")
    public Result a(String token, HttpSession session) throws IOException {
        User user = (User) session.getAttribute(sessionKey);
        if(user == null){
            return new Result(0,"请先登录系统",null);
        }
        ValueOperations opsForValue = redisTemplate.opsForValue();
        ScanLoginInfo info = (ScanLoginInfo) opsForValue.get("scanLogin:" + token);
        if(info==null){
            return new Result(-1,"该二维码已失效",null);
        }
        info.setMyinfo(user);
        info.setStatus("扫码成功");
        opsForValue.set("scanLogin:"+token,info,60, TimeUnit.SECONDS);

        //TODO 通知前端pc前端扫码成功,pc要获取用户消息
        sessions.get(token).getBasicRemote().sendText("OK");
        return new Result(1,"扫码成功",null);
    }
    static HashMap<String,Session> sessions = new HashMap<>();

    @OnOpen
    public void onOpen(Session session,@PathParam("token") String token){
        sessions.put(token,session);
        session.getUserProperties().put("token",token);
    }

    @OnClose
    public void onClose(Session session){
        Object token = session.getUserProperties().get("token");
        sessions.remove(token);
    }

    @RequestMapping("autoLogin")
    public Result autoLogin(String token,HttpSession session){
        ValueOperations opsForValue = redisTemplate.opsForValue();
        ScanLoginInfo info = (ScanLoginInfo) opsForValue.get("scanLogin:" + token);
        User user = info.getMyinfo();
        session.setAttribute(sessionKey,user);
        return new Result(1,"登录成功！",user);
    }

    @RequestMapping("getLoginToken")
    public Result getLoginToken(@SessionAttribute(required = false) String loginToken){
        if (loginToken == null){
            return new Result(0,"登录令牌还未生成！",null);
        }else {
            return new Result(1,"登录令牌还已生成！",loginToken);
        }
    }


}

@Data
@NoArgsConstructor
@AllArgsConstructor
class ScanLoginInfo implements java.io.Serializable{
    String uuid;
    String status = "未扫码";
    User myinfo;
}
